﻿@using Radzen
@using Radzen.Blazor
@using System.Collections.Generic
@using Microsoft.AspNetCore.Components
@using System.Text.Json
@inject IJSRuntime JSRuntime

<RadzenStack Gap="1rem">
    <RadzenStack Orientation="Radzen.Orientation.Horizontal" Gap="0.5rem" Wrap="FlexWrap.Wrap">
        <RadzenButton Text="格式化" Icon="auto_fix_high"
                      Click="@FormatJson" Size="ButtonSize.Small"
                      ButtonStyle="Radzen.ButtonStyle.Secondary" />
        <RadzenButton Text="压缩" Icon="compress"
                      Click="@MinifyJson" Size="ButtonSize.Small"
                      ButtonStyle="Radzen.ButtonStyle.Secondary" />
        <RadzenButton Text="验证" Icon="check_circle"
                      Click="@ValidateJson" Size="ButtonSize.Small"
                      ButtonStyle="Radzen.ButtonStyle.Info" />
        @*<RadzenButton Text="清空" Icon="clear"
            Click="@ClearJson" Size="ButtonSize.Small"
            ButtonStyle="Radzen.ButtonStyle.Light" />*@
    </RadzenStack>

    <!-- 验证状态显示 -->
    @if (validationMessage != null)
    {
        <RadzenAlert AllowClose="false" AlertStyle="@(isValid ? AlertStyle.Success : AlertStyle.Danger)"
                     Variant="Variant.Flat" Size="AlertSize.Small">
            @validationMessage
        </RadzenAlert>
    }

    <!-- JSON 编辑器 -->
    <RadzenFormField Text="JSON 内容" Style="width: 100%;">
        <div class="editor-container">
            <div class="line-numbers" @ref="lineNumbersRef">
                @for (int i = 1; i <= lineCount; i++)
                {
                    <div class="line-number">@i</div>
                }
            </div>
            <textarea @bind="jsonContent"
                      @bind:event="oninput"
                      @ref="textAreaRef"
                      placeholder="请输入 JSON 内容..."
                      class="json-editor"
                      @onscroll="@OnEditorScroll"
                      spellcheck="false"></textarea>
        </div>
    </RadzenFormField>
</RadzenStack>

<RadzenStack Orientation="Radzen.Orientation.Horizontal" Gap="1rem" JustifyContent="JustifyContent.End">
    <RadzenButton Text="保存" ButtonStyle="Radzen.ButtonStyle.Primary"
                  Click="@SaveJson"
                  Disabled="@(!isValid || string.IsNullOrWhiteSpace(jsonContent))" />
</RadzenStack>

<style>
    .editor-container {
        position: relative;
        display: flex;
        border: 1px solid #ddd;
        border-radius: 4px;
        background-color: #f8f9fa;
        overflow: hidden;
        height: 600px;
    }

    .line-numbers {
        background-color: #f0f0f0;
        border-right: 1px solid #ddd;
        padding: 10px 8px;
        min-width: 50px;
        text-align: right;
        font-family: 'Consolas', 'Monaco', monospace;
        font-size: 14px;
        line-height: 1.5;
        color: #666;
        user-select: none;
        overflow: hidden;
        white-space: nowrap;
        flex-shrink: 0;
    }

    .line-number {
        height: 21px;
        line-height: 21px;
        display: block;
    }

    .json-editor {
        flex: 1;
        border: none;
        outline: none;
        background-color: transparent;
        line-height: 1.5;
        tab-size: 2;
        white-space: pre;
        padding: 10px;
        margin: 0;
        resize: none;
        font-family: 'Consolas', 'Monaco', monospace;
        font-size: 14px;
        overflow: auto;
    }

        .json-editor:focus {
            outline: none;
        }

    .editor-container:focus-within {
        border-color: #007bff;
        box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
    }

    .rz-dialog {
        max-width: 90vw;
        max-height: 90vh;
        width: 800px;
    }

    .rz-dialog-content {
        overflow-y: auto;
    }
</style>

@code {
    private string _jsonContent = "";
    private string jsonContent
    {
        get => _jsonContent;
        set
        {
            if (_jsonContent != value)
            {
                _jsonContent = value;
                UpdateLineCount();
                ValidateJson();
                _ = SyncScroll();
            }
        }
    }

    private bool isValid = false;
    private string validationMessage = null;
    private int lineCount = 1;
    private ElementReference lineNumbersRef;
    private ElementReference textAreaRef;

    private DialogOptions dialogOptions = new DialogOptions()
    {
        Resizable = true,
        Draggable = true,
        CloseDialogOnOverlayClick = false,
        CloseDialogOnEsc = false
    };

    // 事件回调
    [Parameter]
    public EventCallback<string> OnSave { get; set; }

    [Parameter]
    public EventCallback OnCancel { get; set; }

    [Parameter]
    public string InitialContent { get; set; } = "";

    protected override void OnInitialized()
    {
        _jsonContent = InitialContent;
        UpdateLineCount();
        if (!string.IsNullOrWhiteSpace(_jsonContent))
        {
            ValidateJson();
        }
    }

    private void UpdateLineCount()
    {
        if (string.IsNullOrEmpty(_jsonContent))
        {
            lineCount = 1;
        }
        else
        {
            lineCount = _jsonContent.Split('\n').Length;// 计算实际行数（包括空行）
        }
    }

    private async Task OnEditorScroll()
    {
        await SyncScroll();
    }

    private async Task SyncScroll()
    {
        // 同步滚动行号区域
        await JSRuntime.InvokeVoidAsync("syncScroll", textAreaRef, lineNumbersRef);
    }

    private void ValidateJson()
    {
        try
        {
            if (string.IsNullOrWhiteSpace(_jsonContent))
            {
                isValid = false;
                validationMessage = "JSON 内容不能为空";
                return;
            }
            var options = new JsonSerializerOptions
            {
                AllowTrailingCommas = true,
                ReadCommentHandling = JsonCommentHandling.Skip
            }; // 使用 System.Text.Json 验证

            using var document = JsonDocument.Parse(_jsonContent, new JsonDocumentOptions
            {
                AllowTrailingCommas = true,
                CommentHandling = JsonCommentHandling.Skip
            });

            isValid = true;
            validationMessage = "JSON 格式有效";
        }
        catch (System.Text.Json.JsonException ex)
        {
            isValid = false;
            validationMessage = $"JSON 格式错误: {ex.Message}";
        }
        catch (Exception ex)
        {
            isValid = false;
            validationMessage = $"验证失败: {ex.Message}";
        }
    }

    private async Task FormatJson()
    {
        if (!isValid || string.IsNullOrWhiteSpace(_jsonContent))
        {
            return;
        }
        using var document = JsonDocument.Parse(_jsonContent);
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };
        jsonContent = System.Text.Json.JsonSerializer.Serialize(document.RootElement, options);
        await InvokeAsync(StateHasChanged);
    }

    private async Task MinifyJson()
    {
        if (!isValid || string.IsNullOrWhiteSpace(_jsonContent))
        {
            return;
        }
        using var document = JsonDocument.Parse(_jsonContent);
        var options = new JsonSerializerOptions
        {
            WriteIndented = false,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };
        jsonContent = System.Text.Json.JsonSerializer.Serialize(document.RootElement, options);
        await InvokeAsync(StateHasChanged);
    }

    private void ClearJson()
    {
        jsonContent = "";
        isValid = false;
        validationMessage = null;
    }

    private async Task SaveJson()
    {
        if (!isValid || string.IsNullOrWhiteSpace(_jsonContent))
        {
            return;
        }
        await OnSave.InvokeAsync(_jsonContent);
    }
}

<script>
    window.syncScroll = function(textArea, lineNumbers) {
        if (textArea && lineNumbers) {
            lineNumbers.scrollTop = textArea.scrollTop;
        }
    };
</script>